#pragma once 
#include "message.hpp"
#include "net.hpp"

namespace rpc
{
    class CallBack
    {
    public:
        using ptr = std::shared_ptr<CallBack>;
        virtual void onMessage(const BaseConnection::ptr& conn,BaseMessage::ptr& msg) = 0;
    };
    template<class T>
    class CallBackT : public CallBack
    {
    public:
        using ptr = std::shared_ptr<CallBackT>;
        using MessageCallBack = std::function<void(const BaseConnection::ptr& conn,std::shared_ptr<T>& msg)>;
        CallBackT(MessageCallBack handler) : _handler(handler){}
        virtual void onMessage(const BaseConnection::ptr& conn,BaseMessage::ptr& msg) override
        {
            auto type_msg = std::dynamic_pointer_cast<T>(msg);
            _handler(conn,type_msg);
        }
    private:
        MessageCallBack _handler;
    };
    class Dispatcher
    {
    public:
        using ptr = std::shared_ptr<Dispatcher>;
        template<class T>
        void registerHandler(Mtype mtype,const typename CallBackT<T>::MessageCallBack &handler)
        {
            std::unique_lock<std::mutex> lock(_mtx);
            auto cb = std::make_shared<CallBackT<T>>(handler);
            _handlers.insert({mtype,cb});
        }

        void onMessage(const BaseConnection::ptr &conn, BaseMessage::ptr &msg) 
        {
            std::unique_lock<std::mutex> lock(_mtx);
            auto it = _handlers.find(msg->mtype());
            if(it != _handlers.end())
            {
                it->second->onMessage(conn,msg);
                return;
            }
            ELOG("收到未知类型：%d！",(int)msg->mtype());
            conn->shutdown();
        }
    private:
        std::mutex _mtx;
        std::unordered_map<Mtype,CallBack::ptr> _handlers;
    };
}


